www.gusucode.com > VC 自编SQL数据库(服务端+客户端) > VC 自编SQL数据库(服务端+客户端)/code/www.NewXing.com/sql/Server/StepExec.cpp

    // StepExec.cpp : implementation file
//

#include "stdafx.h"
#include "miniSQL.h"
#include "MainFrm.h"
#include "StepExec.h"
#include "LogDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define CMD(DO) m_Cmd.GetAt( m_Cmd.FindIndex( DO ) )

extern CMiniSQLApp theApp;
/////////////////////////////////////////////////////////////////////////////
// CStepExec

CStepExec::CStepExec( CString& str ) :
CLexAnalyzer( str )
{
}

CStepExec::~CStepExec()
{
}

void CStepExec::ErrorKey( int i )
{
	Lex temp = CMD(i);
	if( temp.key == User )
		throw Error( UNKNOWN_ID, 0, temp.str );
	else throw Error( SYNTAX_ERROR, 0, temp.str );
}

CString CStepExec::GetID( int& i )
{
	Lex temp = CMD(++i);
    if( temp.key != User )
        throw Error( SYNTAX_ERROR, 0, temp.str );
    return temp.str;
}

CEntryAttr CStepExec::GetDef( int& i )
{
    CEntryAttr   attr;
    if( CMD(++i).key != LEFT_PAR )
        ErrorKey( i );
    do
    {
        CString		id_name = GetID( i );
        CItemType	type;
        switch( CMD(++i).key )
        {
            case _INT    : type = _INT;		break;
            case _LONG   : type = _LONG;	break;
            case _FLOAT  : type = _FLOAT;	break;
            case _DATE   : type = _DATE;	break;
            case _STRING : 
                if( CMD(++i).key != LEFT_PAR ||
                    CMD(++i).key != Digit    ||
                    CMD(++i).key != RIGHT_PAR )
                    ErrorKey( i );
                type = CItemType( _STRING, atoi( (LPCTSTR)CMD(i-1).str ) );
                if( type.size > 0 )  break;
            default :  Error( SYNTAX_ERROR, 0, CMD(i).str );
        }
        attr.push( CItemAttr( (LPCTSTR)id_name, type ) );
    } while( CMD(++i).key == SEPARATOR );
    --i;
    if( CMD(++i).key != RIGHT_PAR )
        ErrorKey( i );
    return attr;
}

int CStepExec::GetStrs( int& i, STR_LIST& ret, bool id, bool par )
{
    if( par && CMD(++i).key != LEFT_PAR )
        ErrorKey( i );
    do
    {
        i++;
        if( ( id && CMD(i).key != User && CMD(i).key != MUL ) || 
            ( !id && CMD(i).key != String && CMD(i).key != Digit &&	CMD(i).key != NUL ) )
            ErrorKey( i );
        if( CMD(i).key == MUL )
		{
			ret.RemoveAll();
            return 0;
		}
        if( CMD(i).key != NUL )
            ret.AddTail( CMD(i).str );
        else
		{
			char str = -1;
            ret.AddTail( CString(str) );
		}
    } while( CMD(++i).key == SEPARATOR );
    --i;
    if( par && CMD(++i).key != RIGHT_PAR )
        ErrorKey( i );
    return ret.GetCount();
}

CString CStepExec::GetStr( int& i, bool id, bool par )
{
	CString str;

    if( par && CMD(++i).key != LEFT_PAR )
        ErrorKey( i );
	i++;
	if( ( id && CMD(i).key != User ) || 
		( !id && CMD(i).key != String && CMD(i).key != Digit &&	CMD(i).key != NUL ) )
		ErrorKey( i );
	if( CMD(i).key != NUL )
		str = CMD(i).str;
	else
	{
		char a = -1;
		str= CString( a );
	}
    if( par && CMD(++i).key != RIGHT_PAR )
        ErrorKey( i );
	return str;
}

void CStepExec::GetCondition( CTable& table, int& i, RESULT& ret )
{
	if( CMD(i+1).key != WHERE )
	{
		table.search( ret );
		return ;
	}
	i++;
	STR_PAIR equ, bet1, bet2;
	CString str;
	do
	{
		switch( CMD(i+2).key )
		{
		case EQU:
			equ.first.AddTail( GetStr( i, true ) );
			i++;
			equ.second.AddTail( GetStr( i, false ) );
			break;
		case BETWEEN:
			str = GetStr( i, true );
			bet1.first.AddTail( str );
			bet2.first.AddTail( str );
			i++;
			bet1.second.AddTail( GetStr( i, false ) );
			if( CMD(++i).key != AND )
				ErrorKey( i );
			bet2.second.AddTail( GetStr( i, false ) );
			break;
		default:
			ErrorKey( i+2 );
		}
	}while( CMD(++i).key == AND );
	i--;
	if( equ.first.GetCount() && !bet1.first.GetCount() )
	{
		table.search( ret, equ );
		return ;
	}
	else if( !equ.first.GetCount() && bet1.first.GetCount() )
		table.search( ret, bet1, bet2 );
	else if( equ.first.GetCount() && bet1.first.GetCount() )
		table.search( ret, equ, bet1, bet2 );
	else
		throw Error();
}


void CStepExec::GetSet( int& i, STR_PAIR& ret )
{
	do
	{
		ret.first.AddTail( GetStr( i, true ) );
		if( CMD(++i).key != EQU )
			ErrorKey( i );
		ret.second.AddTail( GetStr( i, false ) );
	}while( CMD(++i).key == SEPARATOR );
	i--;
}

void CStepExec::Exec()
{
	m_Cmd.RemoveAll();
	m_Cmd.AddTail( CLexAnalyzer::NextToken() );
	while( m_Cmd.GetTail().key != EndOfFile )
	{		
		if( m_Cmd.GetTail().key == SEMICOLON )
		{
			StepExec();
			m_Cmd.RemoveAll();
		}
		m_Cmd.AddTail( CLexAnalyzer::NextToken() );
	}
}

void CStepExec::SingleExec()
{
	m_Cmd.RemoveAll();
	do 
		m_Cmd.AddTail( CLexAnalyzer::NextToken() );
	while( m_Cmd.GetTail().key != EndOfFile && m_Cmd.GetTail().key != SEMICOLON );

	if( m_Cmd.GetTail().key == SEMICOLON )
		StepExec();
}

void CStepExec::StepExec()
{
	int i = 0;
	switch( CMD(i++).key )
	{
	case CREATE:
		if( (theApp.m_LogType & LOG_SUPERUSER) || (theApp.m_LogType & LOG_ADMIN) )
			if( CMD(i).key == _TABLE )
			{
				CString		tname = GetID( i );
				CEntryAttr	attr = GetDef( i );
				if ( CMD(++i).key != SEMICOLON )
					throw Error( SYNTAX_ERROR, 0, CMD(i).str );
				CTable table( (LPCTSTR)tname, attr );
				theApp.OnRefreshFileTree();
				table.close();
				Message( (CString)"Successful : Created table \"" + tname +"\"\n" );
			}
			else if( CMD(i).key == INDEX ||
					 CMD(i).key == UNIQUE && CMD(i+1).key == INDEX )
			{
				bool	dup = true;
				if( CMD(i).key == UNIQUE )
					dup = false, ++i;
				CString iname = GetID( i );
				if( CMD(++i).key != ON )
					ErrorKey( i );
				CString   tname = GetID( i );
				STR_LIST name_list;
				GetStrs( i, name_list, true, true );
				if( CMD(++i).key != SEMICOLON )
					throw Error( SYNTAX_ERROR, 0, CMD(i).str );
				CTable( (LPCTSTR)tname ).create_index( (LPCTSTR)iname, name_list, dup );
				CMainFrame* pMainFrm = ( CMainFrame* )AfxGetMainWnd();
				pMainFrm->m_FileBar.InsertIndex( tname, iname );
				Message( (CString)"Successful : Created index \"" + iname +".bpt\" on table \"" + tname + "\"\n" );
			}
			else ErrorKey( i );
		else
			throw Error( ERROR_AUTHOR, 0, _T("") );
		break;
	case INSERT:
		if( (theApp.m_LogType & LOG_SUPERUSER) || (theApp.m_LogType & LOG_ADMIN) )
		{
			if( CMD(i).key != INTO )
				i--;
			CString tname = GetID( i );
			STR_PAIR input;
			if( CMD(i+1).key == LEFT_PAR )
				GetStrs( i, input.first, true, true );
			if( CMD(++i).key != VALUES )
				ErrorKey( i );
			GetStrs( i, input.second, false, true );
			if( CMD(++i).key != SEMICOLON )
				throw Error( SYNTAX_ERROR, 0, CMD(i).str );
			CTable table( (LPCTSTR)tname );
			table.insert( input );
			Message( "Operation insert successful.\n" );
		}
		else
			throw Error( ERROR_AUTHOR, 0, _T("") );
		break;
	case SELECT:
		{
			STR_LIST name_list;
			GetStrs( --i, name_list, true );
			if( CMD(++i).key != FROM )
				ErrorKey( i );
			CString tname = GetID( i );
			if( !name_list.GetCount() && CMD(i+1).key == SEMICOLON )
			{
				CString tpath( theApp.dir );
				tpath = tpath + "\\" + tname + ".msl";
				CMSLDoc* pDoc;
				if( pDoc = theApp.IsDocExist( tname + ".msl" ) )
					pDoc->OnCloseDocument();
				theApp.OpenDocumentFile( tpath );
				break;
			}
			CTable table( (LPCTSTR) tname );
			RESULT res;
			GetCondition( table, i, res );
			if( CMD(++i).key != SEMICOLON )
				throw Error( SYNTAX_ERROR, 0, CMD(i).str );
			table.select( res, name_list );
			table.close();
			CString temp;
			temp.Format( "Select successful : Total %d entries selected.\n", res.GetCount() );
			Message( temp );
		}
		break;
	case _DELETE:
		if( (theApp.m_LogType & LOG_SUPERUSER) || (theApp.m_LogType & LOG_ADMIN) )
			if( CMD(i).key == FROM )
			{
				CTable table( (LPCTSTR) GetID( i ) );
				RESULT res;
				GetCondition( table, i, res );
				if( CMD(++i).key != SEMICOLON )
					throw Error( SYNTAX_ERROR, 0, CMD(i).str );
				table.remove( res );
				CString temp;
				temp.Format( "Delete successful : Total %d entries deleted.\n", res.GetCount() );
				Message( temp );
			}
			else ErrorKey( i );
		else
			throw Error( ERROR_AUTHOR, 0, _T("") );
		break;
	case UPDATE:
		if( (theApp.m_LogType & LOG_SUPERUSER) || (theApp.m_LogType & LOG_ADMIN) )
		{
			CTable table( (LPCTSTR)GetID( --i ) );
			if( CMD(++i).key != SET )
				ErrorKey( i );
			STR_PAIR set;
			GetSet( i, set );
			RESULT res;
			GetCondition( table, i, res );
			if( CMD(++i).key != SEMICOLON )
				throw Error( SYNTAX_ERROR, 0, CMD(i).str );
			table.update( res, set );
			CString temp;
			temp.Format( "Update successful : Total %d entries updated.\n", res.GetCount() );
			Message( temp );
		}
		else
			throw Error( ERROR_AUTHOR, 0, _T("") );
		break;
	case DROP:
		if( (theApp.m_LogType & LOG_SUPERUSER) || (theApp.m_LogType & LOG_ADMIN) )
			if( CMD(i).key == _TABLE )
			{
				CString tname = GetID( i );
				if( CMD(++i).key != SEMICOLON )
					throw Error( SYNTAX_ERROR, 0, CMD(i).str );
				CTable( (LPCTSTR)tname ).drop();
				CMainFrame* pMainFrm = ( CMainFrame* )theApp.m_pMainWnd;
				pMainFrm->m_FileBar.DelFile( tname );
				Message( (CString)"Successful : Dropped table \"" + tname +"\"\n" );
			}
			else if( CMD(i).key == INDEX )
			{
				CString iname = GetID( i );
				if( CMD(++i).key != ON )
					throw Error( SYNTAX_ERROR, 0, CMD(i).str );
				CString tname = GetID( i );
				if( CMD(++i).key != SEMICOLON )
					throw Error( SYNTAX_ERROR, 0, CMD(i).str );
				CTable( (LPCTSTR)tname ).drop_index( (LPCTSTR)iname );
				CMainFrame* pMainFrm = ( CMainFrame* )AfxGetMainWnd();
				pMainFrm->m_FileBar.DropIndex( tname, iname );
				Message( (CString)"Successful : Dropped index \"" + iname + ".bpt\" on table\"" + tname + "\"\n" );
			}
			else
				ErrorKey( i );
		else
			throw Error( ERROR_AUTHOR, 0, _T("") );
		break;
	case EXIT:
		theApp.Exit();
		break;
	default:
		ErrorKey( --i );
	}
}